package com.example.common.utils;

import com.example.common.entity.AESPKCS7EncryptResult;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;

/**
 * AES工具类
 * 加密解密参考微信小程序对于userProfile的加解密
 * 对称解密使用的算法为 AES-128-CBC，数据采用PKCS#7填充。
 * 对称解密的目标密文为 Base64_Decode(encryptedData)。
 * 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
 * 对称解密算法初始向量 为Base64_Decode(iv)，其中iv由数据接口返回。
 * 加密相反
 */
public class AESUtils {
    private static final Charset UTF_8 = StandardCharsets.UTF_8;
    ;

    private static final String ALGORITHM = "AES/CBC/NoPadding";


    public static AESPKCS7EncryptResult encrypt(String rawMsg) {
        ByteGroup byteGroup = new ByteGroup();
        byte[] padBytes = PKCS7Encoder.encode(rawMsg.getBytes(UTF_8).length);
        IvParameterSpec iv = generateIv();
        SecretKey secretKey = generateKey(128);
        byteGroup.addBytes(rawMsg.getBytes(UTF_8));
        byteGroup.addBytes(padBytes);
        byte[] encodeStr = byteGroup.toBytes();

        if ((iv != null) && (secretKey != null)) {
            try {
                AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
                params.init(iv);
                Cipher cipher = Cipher.getInstance(ALGORITHM);
                cipher.init(1, new SecretKeySpec(secretKey.getEncoded(), "AES"), params);
                String encryptedData = new String(Base64.encodeBase64(cipher.doFinal(encodeStr)), UTF_8);
                return new AESPKCS7EncryptResult(encryptedData, Base64.encodeBase64String(iv.getIV()), Base64.encodeBase64String(secretKey.getEncoded()));
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    public static String decrypt(String sessionKey, String encryptedData, String ivStr) {
        try {
            AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
            params.init(new IvParameterSpec(Base64.decodeBase64(ivStr)));
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            cipher.init(2, new SecretKeySpec(Base64.decodeBase64(sessionKey), "AES"), params);
            return new String(PKCS7Encoder.decode(cipher.doFinal(Base64.decodeBase64(encryptedData))), UTF_8);
        } catch (Exception var5) {
            return null;
        }
    }

    private static IvParameterSpec generateIv() {
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        return new IvParameterSpec(iv);
    }

    private static SecretKey generateKey(int n) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(n);
            SecretKey key = keyGenerator.generateKey();
            return key;
        } catch (Exception e) {
            return null;
        }
    }

}
